#include "Pentagon.h"
#include <QtMath>

Pentagon::Pentagon(const QPointF& pos) : CloseShape(pos) {
    m_size = { 65, 65 };
}

Pentagon::Pentagon(const Pentagon& other) : CloseShape(other) {}

std::shared_ptr<IShape> Pentagon::clone() const {
    return std::make_shared<Pentagon>(*this);
}

std::unique_ptr<IShape> Pentagon::init(const QPointF& pos) {
    return std::make_unique<Pentagon>(pos);
}

std::vector<QPointF> Pentagon::getVertices() const {
    QRectF rect = bounds();
    QPointF center = rect.center();
    qreal radius = qMin(rect.width(), rect.height()) / 2;
    std::vector<QPointF> vertices;
    vertices.reserve(5);

    for (int i = 0; i < 5; ++i) {
        qreal angle = 2 * M_PI * i / 5 - M_PI / 2;
        vertices.emplace_back(
            center.x() + radius * cos(angle),
            center.y() + radius * sin(angle)
        );
    }
    return vertices;
}

QString Pentagon::toSVG() const {
    auto vertices = getVertices();
    QString pointsStr;
    for (const auto& p : vertices) {
        pointsStr += QString("%1,%2 ").arg(p.x()).arg(p.y());
    }
    pointsStr.chop(1);

    return QString("<polygon %1 points=\"%2\" />")
        .arg(svgAttributes())
        .arg(pointsStr);
}

std::unique_ptr<Pentagon> Pentagon::createFromSVG(const QDomElement& element) {
    auto pentagon = std::make_unique<Pentagon>();

    if (!pentagon->parseSVGAttributes(element)) {
        return nullptr;
    }

    QStringList points = element.attribute("points").split(' ', Qt::SkipEmptyParts);
    if (points.size() != 5) return nullptr;

    QVector<QPointF> vertices;
    for (const QString& point : points) {
        QStringList coords = point.split(',');
        if (coords.size() != 2) return nullptr;

        bool ok;
        qreal x = coords[0].toDouble(&ok);
        if (!ok) return nullptr;
        qreal y = coords[1].toDouble(&ok);
        if (!ok) return nullptr;

        vertices.append(QPointF(x, y));
    }

    qreal minX = std::min_element(vertices.begin(), vertices.end(),
        [](const QPointF& a, const QPointF& b) { return a.x() < b.x(); })->x();
    qreal maxX = std::max_element(vertices.begin(), vertices.end(),
        [](const QPointF& a, const QPointF& b) { return a.x() < b.x(); })->x();
    qreal minY = std::min_element(vertices.begin(), vertices.end(),
        [](const QPointF& a, const QPointF& b) { return a.y() < b.y(); })->y();
    qreal maxY = std::max_element(vertices.begin(), vertices.end(),
        [](const QPointF& a, const QPointF& b) { return a.y() < b.y(); })->y();

    pentagon->setPos(QPointF(minX, minY));
    pentagon->setSize(QSizeF(maxX - minX, maxY - minY));

    return pentagon;
}

QPainterPath Pentagon::shape() const {
    QPainterPath path;
    auto vertices = getVertices();
    path.moveTo(vertices[0]);
    for (size_t i = 1; i < vertices.size(); ++i) {
        path.lineTo(vertices[i]);
    }
    path.closeSubpath();
    return path;
}

std::vector<QPointF> Pentagon::linkPoints() const {
    auto vertices = getVertices();
    QPointF center = std::accumulate(vertices.begin(), vertices.end(), QPointF(0, 0)) / 5;
    std::vector<QPointF> links = { center };
    links.insert(links.end(), vertices.begin(), vertices.end());
    return links;
}